#include "taskitem.h"

TaskItem::TaskItem(QWidget *parent)
    : QWidget{parent}
{
    m_checkbox.setText("taskName");
    m_verticalLayout.addWidget(&m_checkbox);
    setLayout(&m_verticalLayout);
}

QJsonArray TaskItem::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    attribute.insert("name", m_checkbox.text());
    info.append(attribute);
    return info;
}

const QMap<QString, QString> &TaskItem::getParam() const
{
    return m_param;
}

void TaskItem::setTaskName(const QString &name)
{
    m_checkbox.setText(name);
}

void TaskItem::setClick(bool click)
{
    m_checkbox.setChecked(click);
}

void TaskItem::setAlgorithm(AlgorithmStrategy *algorithm)
{
    m_algorithm = algorithm;
}

const AlgorithmStrategy *TaskItem::getAlgorithm()
{
    return m_algorithm;
}

void TaskItem::method(Mat &mask, QPixmap *m_tmpPic, QPixmap *m_pic)
{
    if(m_algorithm)
        m_algorithm->methodAS(mask, m_tmpPic, m_pic);
}

bool TaskItem::isClicked()
{
    return m_checkbox.isChecked();
}

void TaskItem::setWindowParam(QPixmap *pic, QPixmap *tmpPic, Mat *mask)
{
    m_pic = pic;
    m_tmpPic = tmpPic;
    m_mask = mask;
}

void TaskItem::taskStateChange(const bool &state)
{
    if(!(*m_pic).isNull())
    {
        setClick(state);
        emit updateTask();
    }
    else
    {
        m_checkbox.setChecked(false);
        QMessageBox::warning(this, "警告", "没有导入图片");
    }
}
// --------------  简单工厂 --------------

TaskItem *AbstractFactory::createTaskItem(const QString &name)
{
    QMap<QString, TaskItem*> m_hash{
        {"固定二值化", new FixeBinarization()},
        {"自适应二值化",new AdaptiveBinarization()},
        {"腐蚀",new Corrode()},
        {"膨胀",new Swell()},
        {"中值滤波",new Median()},
        {"高斯滤波",new Guess()},
        {"均值滤波",new Mean()},
        {"Canny",new canny()},
        {"Sobel",new sobel()},
        {"Laplacian",new laplacian()},
        {"直方图均衡化",new EqualizeHist()},
        {"RGB转HSV",new RGBtoHSV()},
        {"HSV转RGB",new HSVtoRGB()},
        };
    auto it = m_hash.find(name);
    if(it != m_hash.end())
        return it.value();
    return nullptr;
}

Binarization::Binarization()
{
    resize(160, 120);  // 设置widget大小
    m_horizontalSlider.setOrientation(Qt::Horizontal);   // 水平
    m_label.setText("阈值:");
    m_spinBox.setMaximum(255);
    m_horizontalSlider.setRange(0,255);

    m_layout.addWidget(&m_label);
    m_layout.addWidget(&m_spinBox);
    m_layout.addWidget(&m_horizontalSlider);
    m_widget.setLayout(&m_layout);

    m_verticalLayout.addWidget(&m_widget);

    // 绑定信号
    void (QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, &m_horizontalSlider, &QSlider::setValue);
    connect(&m_horizontalSlider, &QSlider::valueChanged, &m_spinBox, &QSpinBox::setValue);
}

FixeBinarization::FixeBinarization()
{
    setTaskName("固定二值化");
    m_comboBox.addItems(QStringList({"binary", "tozero", "trunc"}));
    m_verticalLayout.addWidget(&m_comboBox);

    // 算法实现
    // 1.设置算法
    BinaryAS *bAS = new BinaryAS(m_comboBox.currentText());
    setAlgorithm(bAS);

    // 2.建立槽函数
    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);

    void(QComboBox::* signal_index)(int) = &QComboBox::currentIndexChanged;
    connect(&m_comboBox, signal_index, this, [=](int index){
        m_param["类型"] = m_comboBox.itemText(index);
        if(index >= 0)
        {
            if(m_checkbox.isChecked())  // 勾选
            {
                bAS->setName(m_comboBox.itemText(index));
                method(*m_mask, m_tmpPic, m_pic);   // 调用对应算法
                emit updatePicture();               // 发送图片更新信号
            }
        }
    });

    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, [=](int threshold){
        bAS->setThreshold(threshold);
        m_param["阈值"] = QString::number(threshold);
        if(m_checkbox.isChecked())
        {
            method(*m_mask, m_tmpPic, m_pic);
            emit updatePicture();
        }
    });
}

QJsonArray FixeBinarization::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    QJsonObject param;
    param.insert("阈值", m_spinBox.text());
    param.insert("类型", m_comboBox.currentText());

    attribute.insert("name", m_checkbox.text());
    attribute.insert("param", param);

    info.append(attribute);
    return info;
}

void FixeBinarization::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return;
    m_spinBox.setValue(param["阈值"].toInt());
    m_comboBox.setCurrentText(param["类型"]);

    auto tmp = const_cast<AlgorithmStrategy*>(getAlgorithm());
    BinaryAS* bAS = dynamic_cast<BinaryAS*>(tmp);
    bAS->setMaxValue(param["阈值"].toInt());
    bAS->setName(param["类型"]);
}

AdaptiveBinarization::AdaptiveBinarization()
{
    setTaskName("自适应二值化");
    m_label.setText("最大值");
    m_comboBox.addItems(QStringList({"OSTU", "TRIANGLE"}));
    m_verticalLayout.addWidget(&m_comboBox);

    // 算法实现
    // 1.设置算法
    BinaryAS *bAS = new BinaryAS(m_comboBox.currentText());
    setAlgorithm(bAS);

    // 2.建立槽函数
    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);

    void(QComboBox::* signal_index)(int) = &QComboBox::currentIndexChanged;
    connect(&m_comboBox, signal_index, this, [=](int index){
        m_param["类型"] = m_comboBox.itemText(index);
        if(index >= 0)
        {
            if(m_checkbox.isChecked())  // 勾选
            {
                bAS->setName(m_comboBox.itemText(index));
                method(*m_mask, m_tmpPic, m_pic);   // 调用对应算法
                emit updatePicture();               // 发送图片更新信号
            }
        }
    });

    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, [=](int maxVal){
        bAS->setMaxValue(maxVal);
        m_param["最大值"] = QString::number(maxVal);
        if(m_checkbox.isChecked())
        {
            method(*m_mask, m_tmpPic, m_pic);
            emit updatePicture();
        }
    });
}

QJsonArray AdaptiveBinarization::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    QJsonObject param;

    param.insert("最大值", m_spinBox.text());
    param.insert("类型", m_comboBox.currentText());

    attribute.insert("name", m_checkbox.text());
    attribute.insert("param", param);

    info.append(attribute);
    return info;
}

void AdaptiveBinarization::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return;
    m_spinBox.setValue(param["最大值"].toInt());
    m_comboBox.setCurrentText(param["类型"]);

    auto tmp = const_cast<AlgorithmStrategy*>(getAlgorithm());
    BinaryAS* bAS = dynamic_cast<BinaryAS*>(tmp);
    bAS->setMaxValue(param["最大值"].toInt());
    bAS->setName(param["类型"]);
}
// --------------------- 形态学处理 ------------------------
Morphological::Morphological()
{
    resize(160,110);
    m_widget.setLayout(&m_layout);
    m_layout.addWidget(&m_radioBtn1, 0, 0);
    m_layout.addWidget(&m_radioBtn2, 0, 1);
    m_layout.addWidget(&m_label, 1, 0);
    m_layout.addWidget(&m_spinBox, 1, 1);

    m_radioBtn1.setText("矩形");
    m_radioBtn2.setText("圆形");
    m_label.setText("核大小");
    m_spinBox.setMaximum(21);
    m_spinBox.setMinimum(1);
    m_radioBtn1.setChecked(true);   // 默认第一个被选中
    m_verticalLayout.addWidget(&m_widget);
}

QJsonArray Morphological::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    QJsonObject param;

    if(m_radioBtn1.isChecked())
        param.insert("类型", m_radioBtn1.text());
    else
        param.insert("类型", m_radioBtn2.text());

    param.insert("核大小", m_spinBox.text());
    attribute.insert("name", m_checkbox.text());
    attribute.insert("param", param);

    info.append(attribute);
    return info;
}

void Morphological::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return ;
    if(param["类型"] == "矩形")
    {
        m_radioBtn1.setChecked(true);
    }
    else if(param["类型"] == "圆形")
    {
        m_radioBtn2.setChecked(true);
    }
    m_spinBox.setValue(param["核大小"].toInt());

    auto tmp = const_cast<AlgorithmStrategy*>(getAlgorithm());
    MorphologicalAS* mAS = dynamic_cast<MorphologicalAS*>(tmp);
    mAS->setKernel(param["核大小"].toInt());
    mAS->setShape(param["类型"]);
}

void Morphological::radioCheck(bool check)
{
    if(m_radioBtn1.isChecked())
    {
        m_param["类型"] = m_radioBtn1.text();
        m_mAS->setShape(m_radioBtn1.text());
    }
    else if(m_radioBtn2.isChecked())
    {
        m_param["类型"] = m_radioBtn2.text();
        m_mAS->setShape(m_radioBtn2.text());
    }
    if(m_checkbox.isChecked())
    {
        if(check)
        {
            method(*m_mask, m_tmpPic, m_pic);
            emit updatePicture();
        }
    }
}

void Morphological::spinboxChange(int kernal)
{
    m_mAS->setKernel(kernal);
    m_param["核大小"] = m_spinBox.text();
    if(m_checkbox.isChecked())
    {
        method(*m_mask, m_tmpPic, m_pic);
        emit updatePicture();
    }
}

Corrode::Corrode()
{
    setTaskName("腐蚀");

    // 算法实现
    // 1.设置算法
    if(m_radioBtn1.isChecked())
        m_mAS = new MorphologicalAS("腐蚀", m_radioBtn1.text(), m_spinBox.text().toInt());
    else
        m_mAS = new MorphologicalAS("腐蚀", m_radioBtn2.text(), m_spinBox.text().toInt());
    setAlgorithm(m_mAS);

    // 2.建立槽函数
    connect(&m_checkbox, &QCheckBox::clicked, this, &TaskItem::taskStateChange);
    connect(&m_radioBtn1, &QRadioButton::toggled, this, &Morphological::radioCheck);
    connect(&m_radioBtn2, &QRadioButton::toggled, this, &Morphological::radioCheck);
    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, &Morphological::spinboxChange);
}

Swell::Swell()
{
    setTaskName("膨胀");

    // 算法实现
    // 1.设置算法
    if(m_radioBtn1.isChecked())
        m_mAS = new MorphologicalAS("膨胀", m_radioBtn1.text(), m_spinBox.text().toInt());
    else
        m_mAS = new MorphologicalAS("膨胀", m_radioBtn2.text(), m_spinBox.text().toInt());
    setAlgorithm(m_mAS);

    // 2.建立槽函数
    connect(&m_checkbox, &QCheckBox::clicked, this, &TaskItem::taskStateChange);
    connect(&m_radioBtn1, &QRadioButton::toggled, this, &Morphological::radioCheck);
    connect(&m_radioBtn2, &QRadioButton::toggled, this, &Morphological::radioCheck);
    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, &Morphological::spinboxChange);
}

// --------------------- 滤波 ------------------------
Filtering::Filtering()
{
    resize(160,85);
    m_widget.setLayout(&m_layout);
    m_layout.addWidget(&m_label);
    m_layout.addWidget(&m_spinBox);

    m_label.setText("核大小");
    m_spinBox.setMaximum(21);
    m_spinBox.setMinimum(3);
    m_spinBox.setSingleStep(2);  // 每次加两

    m_verticalLayout.addWidget(&m_widget);
}

QJsonArray Filtering::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    QJsonObject param;
    param.insert("核大小", m_spinBox.text());

    attribute.insert("name", m_checkbox.text());
    attribute.insert("param", param);

    info.append(attribute);
    return info;
}

void Filtering::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return ;
    m_spinBox.setValue(param["核大小"].toInt());

    auto tmp = const_cast<AlgorithmStrategy*>(getAlgorithm());
    FilteringAS* mAS = dynamic_cast<FilteringAS*>(tmp);
    mAS->setKernel(param["核大小"].toInt());
}

Guess::Guess()
{
    setTaskName("高斯滤波");
    FilteringAS* fAS = new FilteringAS("高斯滤波");
    setAlgorithm(fAS);

    connect(&m_checkbox, &QCheckBox::clicked, this, &TaskItem::taskStateChange);

    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, [=](int kernal){
        fAS->setKernel(kernal);
        m_param["核大小"] = m_spinBox.text();
        if(m_checkbox.isChecked())
        {
            method(*m_mask, m_tmpPic, m_pic);
            emit updatePicture();
        }
    });

}

Median::Median()
{
    setTaskName("中值滤波");
    FilteringAS* fAS = new FilteringAS("中值滤波");
    setAlgorithm(fAS);

    connect(&m_checkbox, &QCheckBox::clicked, this, &TaskItem::taskStateChange);

    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, [=](int kernal){
        fAS->setKernel(kernal);
        m_param["核大小"] = m_spinBox.text();
        if(m_checkbox.isChecked())
        {
            method(*m_mask, m_tmpPic, m_pic);
            emit updatePicture();
        }
    });
}

Mean::Mean()
{
    setTaskName("均值滤波");
    FilteringAS* fAS = new FilteringAS("均值滤波");
    setAlgorithm(fAS);

    connect(&m_checkbox, &QCheckBox::clicked, this, &TaskItem::taskStateChange);

    void(QSpinBox::* sp_signal)(int) = &QSpinBox::valueChanged;
    connect(&m_spinBox, sp_signal, this, [=](int kernal){
        fAS->setKernel(kernal);
        m_param["核大小"] = m_spinBox.text();
        if(m_checkbox.isChecked())
        {
            method(*m_mask, m_tmpPic, m_pic);
            emit updatePicture();
        }
    });
}
// --------------------- 边缘检测 ------------------------
EdgeDetection::EdgeDetection()
{
    resize(160, 35);
}

QJsonArray EdgeDetection::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    attribute.insert("name", m_checkbox.text());
    info.append(attribute);
    return info;
}

void EdgeDetection::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return ;
}

canny::canny()
{
    setTaskName("Canny");
    EdgeDetectionAS* eAS = new EdgeDetectionAS("Canny");
    setAlgorithm(eAS);
    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);
}

sobel::sobel()
{
    setTaskName("Sobel");
    EdgeDetectionAS* eAS = new EdgeDetectionAS("Sobel");
    setAlgorithm(eAS);
    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);
}

laplacian::laplacian()
{
    setTaskName("Laplacian");
    EdgeDetectionAS* eAS = new EdgeDetectionAS("Laplacian");
    setAlgorithm(eAS);
    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);
}

// --------------------- 直方图均衡化 ---------------------
EqualizeHist::EqualizeHist()
{
    resize(160, 35);
    setTaskName("直方图均衡化");
    EqualizeHistAS* eAS = new EqualizeHistAS("直方图均衡化");
    setAlgorithm(eAS);

    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);
}

QJsonArray EqualizeHist::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    attribute.insert("name", m_checkbox.text());
    info.append(attribute);
    return info;
}

void EqualizeHist::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return;
}


// ------------------- 彩色图像格式转换 -----------------------
ColorTo::ColorTo()
{
    resize(160, 35);
}

QJsonArray ColorTo::toJson()
{
    QJsonArray info;
    QJsonObject attribute;
    attribute.insert("name", m_checkbox.text());
    info.append(attribute);
    return info;
}

void ColorTo::setParam(QMap<QString, QString> &param)
{
    if(param.empty())
        return;
}

RGBtoHSV::RGBtoHSV()
{
    setTaskName("RGB转HSV");
    ColorToAS* cAS = new ColorToAS("RGB转HSV");
    setAlgorithm(cAS);

    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);
}

HSVtoRGB::HSVtoRGB()
{
    setTaskName("HSV转RGB");
    ColorToAS* cAS = new ColorToAS("HSV转RGB");
    setAlgorithm(cAS);

    connect(&m_checkbox, &QCheckBox::toggled, this, &TaskItem::taskStateChange);
}
